<template>
  <div class="camera-container">
    <h2>摄像头截图功能</h2>
    <h3>实时视频流</h3>
    <div class="video-container" @click="handleVideoClick">
      <video ref="video" autoplay playsinline muted></video>
      <div v-if="!hasVideoStream" class="video-overlay">
        <i class="el-icon-video-camera-solid"></i>
        <p>{{ streamError ? '点击重新连接摄像头' : '摄像头未连接' }}</p>
      </div>
    </div>
    <div class="button-group">
      <el-button type="primary" @click="capture" :disabled="!hasVideoStream">
        <i class="el-icon-camera"></i> 截图
      </el-button>
      <el-button type="warning" @click="startCamera">
        <i class="el-icon-refresh"></i> 重新连接摄像头
      </el-button>
    </div>
    <canvas ref="canvas" width="640" height="480" style="display: none;"></canvas>
    <div v-if="capturedImage" class="capture-preview">
      <h3>截图预览</h3>
      <img :src="capturedImage" alt="截图预览" />
      <a :href="capturedImage" :download="`screenshot_${new Date().getTime()}.png`" class="download-btn">
        <el-button type="success">
          <i class="el-icon-download"></i> 下载截图
        </el-button>
      </a>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      video: null,
      canvas: null,
      downloadLink: null,
      hasVideoStream: false,
      capturedImage: null,
      streamError: null
    };
  },
  mounted() {
    console.log('mounted called');
    this.video = this.$refs.video;
    this.canvas = this.$refs.canvas;
    this.downloadLink = this.$refs.downloadLink;

    // 添加视频事件监听
    this.video.addEventListener('canplay', () => {
      console.log('视频准备就绪，可以播放');
      // 标记视频已准备好
      this.hasVideoStream = true;
    });

    // 添加错误事件监听
    this.video.addEventListener('error', (e) => {
      console.error('视频加载错误:', e);
      this.hasVideoStream = false;
    });

    // 使用更健壮的方式获取摄像头流，延迟一点以确保DOM完全加载
    this.$nextTick(() => {
      setTimeout(() => {
        this.startCamera();
      }, 300);
    });
  },

  beforeDestroy() {
    // 组件销毁前释放摄像头资源并移除事件监听器
    this.cleanupResources();
  },

  beforeRouteLeave(to, from, next) {
    // 路由离开前也清理资源
    this.cleanupResources();
    next();
  },

  methods: {
    cleanupResources() {
      // 移除事件监听器
      if (this.video) {
        this.video.onloadedmetadata = null;
        this.video.onended = null;

        // 清理视频源和轨道
        if (this.video.srcObject) {
          try {
            const tracks = this.video.srcObject.getTracks();
            tracks.forEach(track => {
              if (track.readyState === 'live') {
                track.stop();
              }
            });
            this.video.srcObject = null;
          } catch (e) {
            console.error('清理视频资源时出错:', e);
          }
        }
      }

      // 重置状态
      this.hasVideoStream = false;
    },
    startCamera() {
      // 如果已经有流存在并且工作正常，不要重新启动
      if (this.video.srcObject && this.video.srcObject.active && this.hasVideoStream) {
        console.log('摄像头已经开启并工作正常，不需重新启动');
        return;
      }

      // 重置状态
      this.hasVideoStream = false;
      this.streamError = null;

      // 清理之前可能存在的流
      if (this.video.srcObject) {
        try {
          const tracks = this.video.srcObject.getTracks();
          tracks.forEach(track => {
            track.stop();
          });
          this.video.srcObject = null;
          // 等待流完全停止
          setTimeout(() => this.initializeCamera(), 200);
        } catch (e) {
          console.error('清理之前的流时出错:', e);
          this.initializeCamera();
        }
      } else {
        // 没有之前的流，直接初始化
        this.initializeCamera();
      }
    },

    initializeCamera() {
      // 添加视频约束，尝试设置合适的分辨率和帧率
      const constraints = {
        video: {
          width: { ideal: 640 },
          height: { ideal: 480 },
          frameRate: { ideal: 30 }
        },
        audio: false
      };

      // 检查浏览器是否支持getUserMedia
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        this.$message.error('您的浏览器不支持访问摄像头，请使用现代浏览器。');
        return;
      }

      navigator.mediaDevices.getUserMedia(constraints)
        .then(stream => {
          console.log('获取到摄像头流');

          // 确保视频元素存在
          if (!this.video) {
            this.video = this.$refs.video;
          }

          // 设置视频源
          this.video.srcObject = stream;

          // 监听流结束事件
          stream.getVideoTracks()[0].onended = () => {
            console.log('视频流已结束');
            this.hasVideoStream = false;
            this.$message.warning('摄像头已断开');
          };

          // 添加loadedmetadata事件后再播放视频
          this.video.onloadedmetadata = () => {
            console.log('视频元数据已加载，准备播放');
            // 尝试播放视频
            const playPromise = this.video.play();

            if (playPromise !== undefined) {
              playPromise
                .then(() => {
                  console.log('视频开始播放');
                  this.hasVideoStream = true;
                })
                .catch(e => {
                  console.error('视频播放失败:', e);
                  // 如果是用户交互问题，可以提示用户点击屏幕
                  if (e.name === 'NotAllowedError') {
                    this.$message.warning('浏览器需要您的交互才能播放视频，请点击视频区域。');
                  } else {
                    this.$message.error('视频播放失败: ' + e.message);
                  }
                });
            }
          };
        })
        .catch(error => {
          console.error('无法访问摄像头:', error);
          this.streamError = error.message;
          this.hasVideoStream = false;

          // 显示更友好的错误信息给用户
          if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
            this.$message.error('未找到可用的摄像头设备，请确保您的设备已正确连接。');
          } else if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
            this.$message.error('您拒绝了摄像头访问权限，请在浏览器设置中启用摄像头权限。');
          } else if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
            this.$message.error('摄像头设备被占用，请关闭其他可能使用摄像头的应用程序。');
          } else {
            this.$message.error('无法访问摄像头: ' + error.message);
          }
        });
    },

    handleVideoClick() {
      // 如果摄像头未连接，尝试重新连接
      if (!this.hasVideoStream) {
        this.startCamera();
      }

      // 如果视频存在但未播放，尝试手动播放视频
      // 这可以解决一些浏览器要求用户交互才能播放视频的问题
      if (this.video && this.video.paused && this.video.srcObject) {
        this.video.play().catch(e => {
          console.error('点击后播放失败:', e);
        });
      }
    },

    capture() {
      console.log('capture function called');
      if (!this.video.srcObject || !this.hasVideoStream) {
        console.error('没有视频流');
        this.$message.warning('摄像头未就绪，无法截图');
        return;
      }

      const context = this.canvas.getContext('2d');
      // 清除之前的内容
      context.clearRect(0, 0, this.canvas.width, this.canvas.height);
      // 绘制当前视频帧
      context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);

      // 获取图像数据
      const imageDataURL = this.canvas.toDataURL('image/png');
      this.capturedImage = imageDataURL;

      // 可选：显示截图成功的提示
      this.$message.success('截图成功');
    }
  }
};
</script>

<style scoped>
.camera-container {
  text-align: center;
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.video-container {
  position: relative;
  width: 640px;
  height: 480px;
  margin: 0 auto 20px;
  border: 2px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
  background-color: #f2f2f2;
}

video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
}

.video-overlay i {
  font-size: 64px;
  margin-bottom: 20px;
}

.button-group {
  margin: 20px 0;
}


.capture-preview {
  margin-top: 30px;
  padding: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background-color: #f9f9f9;
}

.capture-preview img {
  max-width: 100%;
  max-height: 400px;
  border: 1px solid #ccc;
  margin: 15px 0;
}

.download-btn {
  text-decoration: none;
  display: inline-block;
  margin-top: 10px;
}

.button-group {
  margin: 20px 0;
}



.capture-preview {
  margin-top: 30px;
  padding: 20px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  background-color: #f9f9f9;
}

.capture-preview img {
  max-width: 100%;
  max-height: 400px;
  border: 1px solid #ccc;
  margin: 15px 0;
}

.download-btn {
  text-decoration: none;
  display: inline-block;
  margin-top: 10px;
}
</style>
